// @title           User模块API
// @version         1.0
// @description     This is a sample server celler server.
// @termsOfService  http://swagger.io/terms/

// @contact.name   API Support
// @contact.url    http://www.swagger.io/support
// @contact.email  sage12345678@qq.com

// @license.name  Apache 2.0
// @license.url   http://www.apache.org/licenses/LICENSE-2.0.html

// @host      localhost:8080
// @BasePath  /
// @schemes http https
// @produce      json,html

// @securityDefinitions.basic   BasicAuth

// @securityDefinitions.apikey	ApiKeyAuth
// @in							header
// @name						Authorization
// @description					Api-Token, Header: Authorization

// @externalDocs.description  OpenAPI
// @externalDocs.url          https://swagger.io/resources/open-api/
package userapp

import (
	"gitee.com/captials-team/ubdframe/src/apps"
	httpController "gitee.com/captials-team/ubdframe/src/apps/userapp/controllers/http"
	"gitee.com/captials-team/ubdframe/src/common"
	"gitee.com/captials-team/ubdframe/src/domain/configstc"
	"gitee.com/captials-team/ubdframe/src/domain/interfaces"
	"gitee.com/captials-team/ubdframe/src/domain/services"
	mysqlDao "gitee.com/captials-team/ubdframe/src/infrastructure/dao/mysql"
	"gitee.com/captials-team/ubdframe/src/pkg/gin_http"
	"gitee.com/captials-team/ubdframe/src/pkg/uber_help"
	"go.uber.org/dig"
)

type App struct {
	*apps.App

	di *dig.Scope

	//rpc和api根据启动情况会有一个为空
	ApiServer *ApiServer
	RpcServer *RpcServer
}

func (app *App) initDao() {
	common.ErrPanic(app.di.Provide(func(conf *configstc.UserAppConfig) (user interfaces.ItfUser, userThird interfaces.ItfUserThird, vtCode interfaces.ItfVerifyCode, loginRecord interfaces.ItfUserLoginRecord) {
		var err error
		user = mysqlDao.NewUserDao(conf.DBConfig)
		userThird = mysqlDao.NewUserThirdDao(conf.DBConfig)
		vtCode = mysqlDao.NewVerifyCodeDao(conf.DBConfig)
		loginRecord = mysqlDao.NewUserLoginRecordDao(conf.DBConfig)

		_, err = user.Migrate()
		common.ErrPanic(err)

		_, err = userThird.Migrate()
		common.ErrPanic(err)

		_, err = vtCode.Migrate()
		common.ErrPanic(err)

		_, err = loginRecord.Migrate()
		common.ErrPanic(err)

		return
	}))

}

func (app *App) initController() {
	common.ErrPanic(app.di.Provide(gin_http.NewCaptchaController, dig.As(new(interfaces.ItfCaptchaController))), uber_help.ErrAlreadyProvided)
	common.ErrPanic(app.di.Provide(httpController.NewUserController, dig.As(new(interfaces.ItfUserCenterController))), uber_help.ErrAlreadyProvided)
	common.ErrPanic(app.di.Provide(httpController.NewAuthController, dig.As(new(interfaces.ItfUserAuthController))), uber_help.ErrAlreadyProvided)
	common.ErrPanic(app.di.Provide(httpController.NewVerifyCodeController, dig.As(new(interfaces.ItfVerifyCodeController))), uber_help.ErrAlreadyProvided)
	common.ErrPanic(app.di.Provide(httpController.NewUserManageController, dig.As(new(interfaces.ItfUserManageController))), uber_help.ErrAlreadyProvided)
}

func (app *App) initService(conf *configstc.UserAppConfig) {
	common.ErrPanic(app.di.Provide(services.NewUserService, dig.As(new(interfaces.ItfUserService))))
}

// initUser 初始化用户
func (app *App) initUser(conf *configstc.UserAppConfig, s interfaces.ItfUserService) {
	for _, u := range conf.AutoCreateUser {
		common.ErrPanic(s.AutoCreateUser(u.UserName, u.Account, u.Password))
	}
}

// NewApp 初始化app
func NewApp(di *dig.Container, conf *configstc.UserAppConfig) *App {
	scope := di.Scope("user")

	common.ErrPanic(scope.Provide(func() *dig.Scope {
		return scope
	}), uber_help.ErrAlreadyProvided)

	common.ErrPanic(scope.Provide(func() *configstc.UserAppConfig {
		return conf
	}), uber_help.ErrAlreadyProvided)

	app := &App{
		di:  scope,
		App: apps.NewApp(di, "user_app"),
	}
	app.WithName(conf.Name)
	app.WithModule(conf.ModuleMode)

	common.ErrPanic(scope.Invoke(app.initDao))
	common.ErrPanic(scope.Invoke(app.initService))
	common.ErrPanic(scope.Invoke(app.initController))
	common.ErrPanic(scope.Invoke(app.initUser)) //初始化用户

	//http api
	if conf.ApiServer.Enable {
		common.ErrPanic(scope.Provide(NewApiServer))
		common.ErrPanic(scope.Invoke(func(api *ApiServer) {
			api.WithModule(conf.ModuleMode)

			app.WithApiServer(api)
			app.ApiServer = api
		}))
	}

	//rpc
	if conf.RpcServer.Enable {
		common.ErrPanic(scope.Provide(NewRpcServer))
		common.ErrPanic(scope.Invoke(func(server *RpcServer) {
			server.WithModule(conf.ModuleMode)

			app.App.WithApiServer(server)
			app.RpcServer = server
		}))
	}

	return app
}
